package com.zhongkun.datahome.service.service.impl;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.zhongkun.datahome.common.constant.HttpStatus;
import com.zhongkun.datahome.common.exception.ServiceException;
import com.zhongkun.datahome.core.repository.SysDictDataRepository;
import com.zhongkun.datahome.service.constant.MaterialChannelEnum;
import com.zhongkun.datahome.service.constant.MaterialTypeEnum;
import com.zhongkun.datahome.service.constant.SysDictTypeEnum;
import com.zhongkun.datahome.service.domain.DecorationStandard;
import com.zhongkun.datahome.service.domain.DecorationStandardItem;
import com.zhongkun.datahome.service.processor.DecoratorStandardItemProcessor;
import com.zhongkun.datahome.service.processor.dto.HouseMaterialDto;
import com.zhongkun.datahome.service.processor.dto.StandardData;
import com.zhongkun.datahome.service.repository.DecorationStandardItemRepository;
import com.zhongkun.datahome.service.repository.DecorationStandardRepository;
import com.zhongkun.datahome.service.req.cmd.sku.SkuCmd;
import com.zhongkun.datahome.service.req.cmd.standard.DecorationStandardCmd;
import com.zhongkun.datahome.service.req.cmd.standard.DecorationStandardItemCmd;
import com.zhongkun.datahome.service.req.qry.sku.SkuQry;
import com.zhongkun.datahome.service.req.qry.standard.DecorationStandardQry;
import com.zhongkun.datahome.service.res.PageVo;
import com.zhongkun.datahome.service.res.sku.SkuVo;
import com.zhongkun.datahome.service.res.standard.DecorationStandardDetailVo;
import com.zhongkun.datahome.service.service.IDecorationStandardService;
import com.zhongkun.datahome.service.service.ISkuService;
import com.zhongkun.datahome.service.utils.ExcelUtil;
import com.zhongkun.datahome.service.utils.StreamUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;

/**
 * 装标Service业务层处理
 *
 * @author ruoyi
 * @date 2025-04-14
 */
@Service
@Slf4j
public class DecorationStandardServiceImpl implements IDecorationStandardService {

    @Resource
    private DecorationStandardRepository decorationStandardRepository;

    @Resource
    private DecorationStandardItemRepository decorationStandardItemRepository;

    @Resource
    private ISkuService skuService;

    @Resource
    private SysDictDataRepository sysDictDataRepository;

    @Override
    public PageVo<DecorationStandard> page(DecorationStandardQry qry) {
        IPage<DecorationStandard> page = decorationStandardRepository.page(qry);
        return PageVo.of(page);
    }

    @Override
    public DecorationStandardDetailVo getInfo(Long id) {
        DecorationStandard decorationStandard = decorationStandardRepository.getById(id);
        if (Objects.isNull(decorationStandard)) {
            throw new ServiceException("装标不存在");
        }

        List<DecorationStandardItem> decorationStandardItems = decorationStandardItemRepository.listByStandardId(id);

        List<DecorationStandardItem> skuItems = decorationStandardItems.stream()
                .filter(item -> MaterialTypeEnum.COMMON_SKU.is(item.getMaterialType()))
                .collect(Collectors.toList());

        if (CollectionUtils.isEmpty(skuItems)) {
            return DecorationStandardDetailVo.of(decorationStandard);
        }

        List<Long> skuIds = skuItems.stream()
                .map(DecorationStandardItem::getMaterialId)
                .collect(Collectors.toList());

        SkuQry qry = new SkuQry();
        qry.setSkuIds(skuIds);
        qry.setPageSize(skuIds.size());
        Map<Long, SkuVo> skuMap = StreamUtil.listToMap(skuService.pageSku(qry).getList(), SkuVo::getId, e -> e);

        DecorationStandardDetailVo result = DecorationStandardDetailVo.of(decorationStandard, skuItems, skuMap);

        // 空间排序
        sysDictDataRepository.sortByLabel(SysDictTypeEnum.HOUSE_MATERIAL_ROOM.getType(), result.getRoomList(), DecorationStandardDetailVo.RoomVo::getRoom);
        return result;
    }

    @Override
    @Transactional
    public Long add(DecorationStandardCmd cmd) {
        if (decorationStandardRepository.countByName(cmd.getStandardName()) > 0) {
            throw new ServiceException("装标名称已存在");
        }

        DecorationStandard toSaveStandard = new DecorationStandardDetailVo();
        toSaveStandard.setStandardName(cmd.getStandardName());
        decorationStandardRepository.save(toSaveStandard);

        if (CollectionUtils.isNotEmpty(cmd.getItemList())) {
            // 保存清单
            List<DecorationStandardItem> toSaveItemList = cmd.getItemList().stream()
                    .map(item -> DecorationStandardItem.of(item, toSaveStandard.getId()))
                    .collect(Collectors.toList());
            decorationStandardItemRepository.saveBatch(toSaveItemList);
        }
        return toSaveStandard.getId();
    }

    @Override
    @Transactional
    public void update(DecorationStandardCmd cmd) {
        DecorationStandard toUpdateStandard = decorationStandardRepository.getById(cmd.getId());
        if (Objects.isNull(toUpdateStandard)) {
            throw new ServiceException("装标不存在");
        }

        if (!StringUtils.equals(toUpdateStandard.getStandardName(), cmd.getStandardName())) {
            if (decorationStandardRepository.countByName(cmd.getStandardName()) > 0) {
                throw new ServiceException("装标名称已存在");
            }
        }

        toUpdateStandard.setStandardName(cmd.getStandardName());
        decorationStandardRepository.updateById(toUpdateStandard);

        List<DecorationStandardItem> oldStandardItems = decorationStandardItemRepository.listByStandardId(toUpdateStandard.getId());

        if (CollectionUtils.isEmpty(cmd.getItemList())) {
            if (CollectionUtils.isNotEmpty(oldStandardItems)) {
                List<Long> toRemoveIds = oldStandardItems.stream().map(DecorationStandardItem::getId).collect(Collectors.toList());
                decorationStandardItemRepository.removeBatchByIds(toRemoveIds);
            }
            return;
        }

        Map<Boolean, List<DecorationStandardItemCmd>> booleanAddMap = cmd.getItemList()
                .stream().collect(Collectors.partitioningBy(item -> Objects.isNull(item.getId())));

        Map<Long, DecorationStandardItemCmd> toUpdateCmdMap = StreamUtil.listToMap(booleanAddMap.get(false), DecorationStandardItemCmd::getId, e -> e);
        List<Long> toRemoveIds = new ArrayList<>();
        List<DecorationStandardItem> toUpdateItemList = new ArrayList<>();

        oldStandardItems.forEach(oldItem -> {
            if (toUpdateCmdMap.containsKey(oldItem.getId())) {
                oldItem.update(toUpdateCmdMap.get(oldItem.getId()));
                toUpdateItemList.add(oldItem);
                return;
            }

            toRemoveIds.add(oldItem.getId());
        });

        List<DecorationStandardItemCmd> toAddCmdList = booleanAddMap.get(true);
        if (CollectionUtils.isNotEmpty(toAddCmdList)) {
            List<DecorationStandardItem> toAddList = toAddCmdList.stream()
                    .map(item -> DecorationStandardItem.of(item, toUpdateStandard.getId()))
                    .collect(Collectors.toList());
            decorationStandardItemRepository.saveBatch(toAddList);
        }

        if (CollectionUtils.isNotEmpty(toRemoveIds)) {
            decorationStandardItemRepository.removeBatchByIds(toRemoveIds);
        }

        if (CollectionUtils.isNotEmpty(toUpdateItemList)) {
            decorationStandardItemRepository.updateBatchById(toUpdateItemList);
        }
    }

    /**
     * 从Excel文件导入装标数据
     *
     * @param standardName 装标名称
     * @param file       Excel文件
     */
    @Override
    @Transactional
    public void importStandardsFromExcel(String standardName, MultipartFile file) {
        // 校验装标ID是否为空
        if (Objects.isNull(standardName)) {
            throw new ServiceException("装标名称不能为空");
        }

        // 校验上传文件是否为空
        if (Objects.isNull(file) || file.isEmpty()) {
            throw new ServiceException("上传的Excel文件为空");
        }

        // 校验装标 ID 是否存在
        if (decorationStandardRepository.countByName(standardName) > 0) {
            throw new ServiceException(standardName + " 名称重复");
        }

        DecorationStandard decorationStandard = new DecorationStandard();
        decorationStandard.setStandardName(standardName);
        decorationStandardRepository.save(decorationStandard);
        try {
            // 解析行数据
            DecoratorStandardItemProcessor processor = new DecoratorStandardItemProcessor();
            EasyExcel.read(file.getInputStream(), StandardData.class, processor).sheet().doRead();
            List<StandardData> standardDataList = processor.getCachedDataList();

            // 解析并上传图片
            Map<Integer, List<String>> imageUrlsMap = ExcelUtil.uploadImageData(file);

            Map<String, List<String>> skuPicUrlsMap = standardDataList.stream()
                    .peek(item -> item.setUrls(imageUrlsMap.getOrDefault(item.getRowIndex(), Collections.emptyList())))
                    .collect(Collectors.toMap(StandardData::getKey, StandardData::getUrls, (v1, v2) -> CollectionUtils.isNotEmpty(v1) ? v1 : v2));

            Map<String, Long> skuMap = skuService.querySkuExist(standardDataList.stream()
                    .map(StandardData::toSkuExistQry)
                    .collect(Collectors.toList()));
            // 创建装标项
            List<DecorationStandardItem> itemList = standardDataList.stream()
                    .map(data -> {
                        DecorationStandardItem item = new DecorationStandardItem();
                        Long skuId = skuMap.get(data.getKey());
                        if (Objects.isNull(skuId)) {
                            //创建sku
                            SkuCmd skuCmd = data.convertSku();
                            skuCmd.setSource("import_from_standard");
                            skuCmd.setPictureUrls(skuPicUrlsMap.get(data.getKey()));
                            skuId = skuService.insertSku(skuCmd);

                            // 为新建商品添加绑定关系
                            skuMap.put(data.getKey(), skuId);
                        }
                        item.setMaterialType(MaterialTypeEnum.COMMON_SKU.getType()); // 假设默认为普通SKU
                        item.setMaterialId(skuId); // 示例ID，实际应根据商品名称查找
                        item.setQuantity(data.getQuantity());
                        item.setStandardId(decorationStandard.getId());
                        item.setChannel(MaterialChannelEnum.getByName(data.getChannel()));
                        item.setRoom(data.getRoom());
                        return item;
                    })
                    .collect(Collectors.toList());

            // 批量保存装标项
            if (CollectionUtils.isNotEmpty(itemList)) {
                decorationStandardItemRepository.saveBatch(itemList);
            }
            log.info("上传装标清单，新增{}条", itemList.size());
        } catch (IOException e) {
            log.error("解析Excel文件失败", e);
            throw new ServiceException("解析Excel文件失败", HttpStatus.ERROR);
        }
    }

    @Override
    @Transactional
    public void remove(List<Long> ids) {
        if (CollectionUtils.isNotEmpty(ids)) {
            decorationStandardRepository.removeBatchByIds(ids);
            decorationStandardItemRepository.removeBatchByStandardIds(ids);
        }
    }
}
